//
// Ishtar C++ Utility Library
//
// Task Facility - Work Header
//

#ifndef __ISHTAR_TASK_WORK_H
#define __ISHTAR_TASK_WORK_H

#include <Ishtar/Ishtar.h>

#if defined( ISHTAR_COMPILER_HAS_PRAGMA_ONCE )
#pragma once
#endif

#include <Ishtar/DateTime.h>
#include <Ishtar/Functional/VoidBinder.h>
#include <Ishtar/InterlockedPointer.h>  
#include <Ishtar/ReferenceCounted.h>    
#include <Ishtar/Task/Detail/WorkStrandRef.h>
#include <Ishtar/Task/TaskFwd.h>


namespace Ishtar
{

namespace Task
{

///////////////////////////////////////////////////////////////////////////////
//
// Work
//
//   THREAD-SAFE : This class is thread-safe. It doesn't need to protect it
//                 when copying and calling.
//

class WorkImpl;

class Work
{
public:

    Work();   // create a "not-a-work". submit it results in nothing.

    Work( const std::string& name, const WorkFunction& workFunc );

    
    //
    // Accessors
    //

    std::string Name() const;

    Bool IsEmpty()     const;  // "Not a work"
    Bool IsCompleted() const;  // "Ran to Completion" or Canceled


    //
    // Order - Set Dependencies
    //

    Work& AddOrder( WorkStrandRef order );


    //
    // Delay or Stall
    // - Delay : schedule the work after due time.
    //   Stall : schedule the work as normal, then execute it after due time.
    //
    //   REMARKS: Delay doesn't block other works, but Stall does.
    //

    Work& DelayFor( Uint delay );  // milliseconds
    Work& DelayFor( const TimeSpan& delay );

    Work& StallFor( Uint stall );  // milliseconds
    Work& StallFor( const TimeSpan& stall );


    //
    // Cancel
    // - false : this work is running or completed
    //   true  : this work is canceled or to be canceled. it won't run.
    //

    Bool Cancel();


    //
    // Operations
    //

    Work Exchange( const Work& rhs );


    //
    // Debugging
    //

    static Uint GetInstanceCount();


private:

    explicit Work( const boost::intrusive_ptr< WorkImpl >& impl );

    InterlockedIntrusivePtr< WorkImpl > m_impl;

    friend class ThreadGroup;
    friend class ThreadPool;
    friend class WorkPoller;
    friend class WorkerThread;

};

ISHTAR_REFERENCE_COUNTED_DECLARE( WorkImpl )


///////////////////////////////////////////////////////////////////////////////
//
// Stand-alone Functions
//

Work MakeWork( const std::string& workName, const WorkFunction& workFunc );
    

} // namespace Task

} // namespace Ishtar

///////////////////////////////////////////////////////////////////////////////
//
// Macros
//

#define ISHTAR_TASK_WORK( var, function, arguments ) \
    Ishtar::Task::Work var( #function, Ishtar::MakeVoidBinder( &function ) arguments )

#define ISHTAR_TASK_MAKE_WORK( function, arguments ) \
    Ishtar::Task::MakeWork( #function, Ishtar::MakeVoidBinder( &function ) arguments )


///////////////////////////////////////////////////////////////////////////////

#endif // __ISHTAR_TASK_WORK_H
